﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LowLevelGraphics
{
    /// <summary>
    /// Use these elements for morphological operations
    /// </summary>
    public static class StructuredElements
    {
        /// <summary>
        /// Lines the specified _n length.
        /// </summary>
        /// <param name="_nLength">Length of the _n.</param>
        /// <param name="_nDegree">The _n degree.</param>
        public static int[] Line(int _nLength, int _nDegree)
        {
            int[] aInt = null;
            if (_nLength != 0)
            {
                if (_nDegree == 0)
                {
                    aInt = new int[_nLength];
                    for (int i = 0; i < aInt.Length; i++)
                    {
                        aInt[i] = 1;
                    }
                }
            }
            return aInt;
        }
    }

    /// <summary>
    /// Use these elements for convolutional operations
    /// </summary>
    public class KernelDefinitions
    {
        /// <summary>
        /// Initializes the <see cref="KernelDefinitions"/> class.
        /// </summary>
        static KernelDefinitions()
        {
        }

        /// <summary>
        /// 
        /// </summary>
        public int[,] EdgeDetection = new int[,]{
            {-1,-1,-1 },
            {0,8,0},
            {-1,-1,-1}
        };

        /// <summary>
        /// 
        /// </summary>
        public int[,] HorizontalLineDetection = new int[,]{
            {-1,-1,-1},
            {2,2,	2},
            {-1,-1,-1}
        };

        /// <summary>
        /// 
        /// </summary>
        public int[,] VerticalLineDetection = new int[,]{
            {-1,2,-1},
            {-1,2,-1},
            {-1,2,-1}
        };

        /// <summary>
        /// 
        /// </summary>
        public int[,] LineUpwardSlope45Degree = new int[,]{
            {-1,-1,2},
            {-1,2,-1},
            {2,-1,-1}
        };

        /// <summary>
        /// 
        /// </summary>
        public int[,] LineDownwardSlope45Degree = new int[,]{
            { 2,-1,-1},
            {-1,2,-1},
            {-1,-1,2}
        };

        /// <summary>
        /// Gaussian kernel 5x5 with o = 1
        /// </summary>
        public int[,] GaussianKernel = new int[,]{
            {1,4,7,4,1},
            {4,16,26,14,4},
            {7,26,41,26,7},
            {4,16,26,14,4},
            {1,4,7,4,1}
        };


        /// <summary>
        /// Vertical Sobel Kernel (5x5)
        /// Baesmann and Kreyss 1998
        /// </summary>
        public int[,] SobelVertical5x5 = new int[,]{
            {-10,-10,0,10,10},
            {-17,-17,0,17,17},
            {-20,-20,0,20,20},
            {-17,-17,0,17,17},
            {-10,-10,0,10,10}
        };

        /// <summary>
        /// Horizontal Sobel Kernel (5x5)
        /// </summary>
        public int[,] SobelHorizontal5x5 = new int[,]{
            {10,17,20,17,10},
            {10,17,20,17,10},
            {0,0,0,0,0},
            {-10,-17,-20,-17,-10},
            {-10,-17,-20,-17,-10}
        };

        /// <summary>
        /// Voss and Suesse 1991
        /// 1/2345
        /// </summary>
        public int[,] LaplaceVoss = new int[,]{
            {0,259,112,259,0},
            {259,-182,-329,-182,259},
            {112,-329,-476,-329,112},
            {259,-182,-329,-182,259},
            {259,-182,-329,-182,259},
            {0,259,112,259,0}

        };

        /// <summary>
        /// Laplace kernel (5x5)
        /// </summary>
        public int[,] Laplace = new int[,]{
            {4,1,0,1,4},
            {1,-2,-3,-2,1},
            {0,-3,-4,-3,0},
            {1,-2,-3,-2,1},
            {4,1,0,1,4}
        };

        /// <summary>
        /// Laplacian of Gaussian kernel (5x5)
        /// </summary>
        public int[,] LaplacianOfGaussian = new int[,]{
            {0,0,-1,0,0},
            {0,-1,-2,-1,0},
            {-1,-2,16,-2,-1},
            {0,-1,-2,-1,0},
            {0,0,-1,0,0}
        };

        /// <summary>
        /// Gausses the kernel1 D.
        /// </summary>
        /// <param name="_nSize">Size of the _n.</param>
        /// <returns></returns>
        public static double[] GaussKernel1D(int _nSize)
        {
            //size = 5

            List<double> aDouble = new List<double>();

            double dY0 = 0;
            double dY = 0;
            float fX = 0;
            float fSigma = 50;

            for (fSigma = 50; fSigma <= 100 + 1; fSigma += 5)
            {
                fSigma = (float)fSigma / 100;

                dY0 = Math.Exp(-Math.Pow(-(_nSize / 2), 2) / (2 * Math.Pow(fSigma, 2)));
                //Debug.WriteLine "sigma = %f:" % sigma
                for (fX = -(_nSize / 2); fX <= _nSize / 2 + 1; fX++)
                {
                    dY = Math.Exp(-Math.Pow(fX, 2) / (2 * Math.Pow(fSigma, 2)));
                    //Debug.WriteLine "integer kernel: %f" % round((y*(1/y0)))
                    //Debug.WriteLine ""
                    aDouble.Add(dY);
                }
            }
            return aDouble.ToArray();
        }
    }
}
